package main

import (
	"fmt"
	"reflect"
)

type User struct {
	Id   int
	Name string
	Age  int
}

func (user User) Hello() {
	fmt.Println("Hello world!")
}

type Manager struct {
	User
	title string
}

func Info(o interface{}) {
	t := reflect.TypeOf(o)
	fmt.Println("Type:", t.Name())

	//反射类型判断
	if k := t.Kind(); k != reflect.Struct {
		fmt.Println("xx")
		return
	}

	v := reflect.ValueOf(o)
	fmt.Println("Fields")
	numField := v.NumField()
	for i := 0; i < numField; i++ {
		f := t.Field(i)
		value := v.Field(i).Interface()
		fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, value)
	}

	for i := 0; i < t.NumMethod(); i++ {
		m := t.Method(i)
		fmt.Printf("%6s:%v\n", m.Name, m.Type)
	}
}

func Set(o interface{}) {
	v := reflect.ValueOf(o)
	if v.Kind() != reflect.Ptr && !v.Elem().CanSet() {
		fmt.Println("XX")
	} else {
		v = v.Elem()
	}

	f := v.FieldByName("Name")
	if !f.IsValid() {
		fmt.Println("BAD")
	}

	if f.Kind() == reflect.String {
		f.SetString("ByeBye")
	}
}

func (user User) Hello1(name string) {
	fmt.Println("Hello", name, "my name is ", user.Name)
}

func main() {
	u := User{1, "OK", 12}
	Info(u)

	manager := Manager{User: User{1, "OK", 12}, title: "123"}
	fmt.Println(manager)
	t := reflect.TypeOf(manager)
	//匿名成员的反射
	fmt.Printf("%#v\n", t.Field(0))
	fmt.Println(t.FieldByIndex([]int{0, 0}))
	fmt.Println(t.FieldByIndex([]int{0, 1}))
	fmt.Println(t.FieldByIndex([]int{0, 2}))
	fmt.Println(t.Field(1))
	//基本类型的反射
	i := 123
	fmt.Println("反射修改前", i)
	v := reflect.ValueOf(&i)
	v.Elem().SetInt(999)
	fmt.Println("反射修改后", i)

	//指针类型的反射
	uptr := &User{1, "OK", 12}
	fmt.Println(*uptr)
	Set(uptr)
	fmt.Println(*uptr)

	//反射调用方法
	u1 := User{1, "OK", 12}
	fmt.Println(u1)
	u1.Hello1("jeo")
	v1 := reflect.ValueOf(u1)
	mv := v1.MethodByName("Hello1")
	mv.Call([]reflect.Value{reflect.ValueOf("jeo")})

}
